import {
  Component,
  OnInit,
  ViewEncapsulation,
  ChangeDetectionStrategy,
  Input,
  AfterViewInit,
  ChangeDetectorRef,
  ViewChild,
  ElementRef,
  Output,
  EventEmitter,
  TemplateRef,
  OnChanges,
  SimpleChanges,
  ViewChildren,
  QueryList,
  OnDestroy,
} from '@angular/core';
import { isNil as _isNil } from 'lodash';
import { SelectNode } from '../../select/interface';
import { LvSelectSM, LvSizeLSD } from '../types';
import { InputBoolean, ResizeObserverObject, ResizeObserverService } from '../api';
import { LvConfig } from '../config';
import { calcMaxTag, TRIGGER_WRAPPER_PADDING } from './select-max-tag-count';

export interface SelectRemoveChangeProps {
  event: MouseEvent;
  node: SelectNode;
}

@Component({
  selector: 'div[lv-internal-select-trigger]',
  templateUrl: './internal-select-trigger.component.html',
  styles: [],
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: {
    class: 'lv-select-wrapper',
    '[class.disabled]': 'lvDisabled',
    '[class.lv-select-trigger-multiple]': 'multiple',
    '[class.lv-select-trigger-size-large]': "lvSize === 'large'",
    '[class.lv-select-trigger-size-small]': "lvSize === 'small'",
    '[class.lv-select-trigger-open]': 'selectOpen',
    '[class.lv-select-trigger-simple]': 'lvSimple',
  },
})
export class InternalSelectTriggerComponent implements OnChanges, OnInit, OnDestroy, AfterViewInit {
  @Input() value: any | any[];
  @Input() lvMaxTagRow: number;
  @Input() selectOpen: boolean;
  @Input() lvPlaceholder: string;
  @Input() lvMaxTagCount: number;
  @Input() lvLoading: boolean = false;
  @Input() lvDisabled: boolean = false;
  @Input() lvShowClear: boolean = false;
  @Input() lvMode: LvSelectSM = 'single'; // 选择模式，默认单选

  @Input() lvSize: LvSizeLSD = 'default';
  @Input() @InputBoolean() lvSimple = false;
  @Input() customTrigger: TemplateRef<void>;

  @Output() clearChange = new EventEmitter<any>(); // 清除全部时回调事件
  @Output() onFoldSelectionChange = new EventEmitter<any>();
  @ViewChild('selectMain') selectMain: ElementRef<HTMLDivElement>;
  @Output() removeChange = new EventEmitter<SelectRemoveChangeProps>(); // 删除单个时回调事件
  @ViewChildren('triggerItem') triggerItem: QueryList<ElementRef<HTMLDivElement>>;

  @ViewChild('selectTriggerCalc', { static: false }) selectTriggerCalc: ElementRef;
  isShowLess = false; // 选中项是否展开全显示
  maxTagCount: number; // 最多显示多少个tag
  INFINITY: number = Infinity;
  public assetsPrefixPath = LvConfig.assetsPrefixPath;

  isSafari = /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
  private _selectLabelBoxEleWidth = 0; // 用于显示选中项的元素宽度
  private _triggerCalcObserver: MutationObserver;

  private selectMainObserver: ResizeObserverObject;

  constructor(
    private _cdr: ChangeDetectorRef,
    private resizeObserverService: ResizeObserverService,
  ) {}

  get multiple(): boolean {
    return this.lvMode === 'multiple';
  }

  // 空
  get empty(): boolean {
    // 是否有选中项, null undefined 空数组
    return _isNil(this.value) || (this.multiple && this.value && !this.value.length);
  }

  ngOnInit(): void {
    this.maxTagCount = this.lvMaxTagCount;
  }

  clearSelected(e: MouseEvent): void {
    this.clearChange.emit(e);
  }

  removeSelectedItem(event: MouseEvent, node: SelectNode): void {
    this.removeChange.emit({ event, node });
  }

  ngOnDestroy(): void {
    this._triggerCalcObserver?.disconnect();
    this.selectMainObserver?.unobserve();
  }

  ngAfterViewInit(): void {
    this._selectLabelBoxEleWidth = this.selectMain.nativeElement.clientWidth;
    this.listenTriggerChange();
  }

  ngOnChanges(changes: SimpleChanges): void {
    if ((changes.lvMode && !changes.lvMode.firstChange) || changes.lvDisabled) {
      setTimeout((): void => this.listenTriggerChange());
    }
  }

  toggleShowLess(event: MouseEvent): void {
    if (this.lvDisabled) {
      return;
    }
    event.stopPropagation();
    this.isShowLess = !this.isShowLess;
    this.onFoldSelectionChange.emit();
  }

  getTriggerMaxHeight(): string {
    if (!this.multiple) {
      return 'none';
    }
    // 0.32 = 每行高度0.24 + 间距0.08，0.06 = 第一行上间距0.03 + 最后一行下间距0.03
    // NEED_DO 组件统一处理动态生成尺寸、间距，替换成获取根节点字体大小*系数，单位为rem
    return this.lvMaxTagCount === Infinity ? 'none' : `${(this.lvMaxTagRow * 0.32 + 0.06) * 100}px`;
  }

  /**
   * 监听trigger children变化，重新计算标签显示
   */
  listenTriggerChange(): void {
    if (!this.multiple || !this.selectTriggerCalc?.nativeElement || this.lvMaxTagCount >= 0) {
      return;
    }
    this._triggerCalcObserver?.disconnect();
    this.selectMainObserver?.unobserve();
    this._triggerCalcObserver = new MutationObserver((): void => {
      this.genMaxTagCount();
    });
    this._triggerCalcObserver.observe(this.selectTriggerCalc.nativeElement, {
      childList: true,
    });
    this.selectMainObserver = this.resizeObserverService.observe(this.selectMain.nativeElement, (): void => {
      this._selectLabelBoxEleWidth = Number(
        window.getComputedStyle(this.selectMain.nativeElement).getPropertyValue('width').slice(0, -2),
      );
      this.genMaxTagCount();
    });
  }

  private genMaxTagCount(): void {
    const selectedValue = this.value || [];
    const itemEleList = this.triggerItem
      .map((item): HTMLDivElement => item.nativeElement)
      .filter((item): boolean => item.parentElement.classList.contains('lv-trigger-item-calc-container'));
    this.maxTagCount = calcMaxTag({
      selectedValue,
      selectionNode: itemEleList,
      selectionWrapperWidth: this._selectLabelBoxEleWidth - TRIGGER_WRAPPER_PADDING,
    });
    this._cdr.markForCheck();
  }
}
